"""
文件名: channels.py
描述: YouTube频道管理API路由

本模块包含以下主要功能：
1. 用户订阅频道列表查询
2. 频道详细信息获取
3. 频道订阅状态管理
4. 频道同步和更新

依赖模块:
   - fastapi: Web框架路由
   - services: YouTube和频道服务
   - models: 数据模型

使用示例:
   >>> GET /channels - 获取用户订阅频道列表
   >>> GET /channels/{id} - 获取频道详细信息
   >>> POST /channels/sync - 同步用户订阅频道
   >>> PUT /channels/{id} - 更新频道信息

注意事项:
   - 频道数据会缓存以减少API调用
   - 支持分页和筛选查询
   - 同步操作可能耗时较长
   - 需要有效的YouTube API权限

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import List, Dict, Any, Optional
import uuid
import time

from fastapi import APIRouter, Depends, HTTPException, status, Query, BackgroundTasks
from pydantic import BaseModel

from src.api.dependencies import (
    get_current_user,
    get_youtube_service,
    get_user_service,
    get_pagination_params,
)
from src.core.logger import get_logger
from src.models.user import User
from src.models.channel import ChannelInDB, ChannelSummary
from src.services.youtube_service import YouTubeService
from src.services.user_service import UserService
from src.utils.exceptions import (
    ValidationException,
    AuthorizationException,
    QuotaExceededException,
)

logger = get_logger(__name__)

router = APIRouter()


class ChannelSyncRequest(BaseModel):
    """频道同步请求模型"""
    force: bool = False
    categories_only: bool = False


@router.get("", response_model=List[ChannelSummary], summary="获取用户订阅频道列表")
async def get_user_channels(
    current_user: User = Depends(get_current_user),
    youtube_service: YouTubeService = Depends(get_youtube_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    category_id: Optional[uuid.UUID] = Query(None, description="筛选指定分类的频道"),
    search: Optional[str] = Query(None, description="频道名称搜索关键词"),
    sort_by: str = Query("name", description="排序字段: name, subscriber_count, updated_at"),
    sort_order: str = Query("asc", description="排序方向: asc, desc"),
) -> List[ChannelSummary]:
    """
    获取当前用户的订阅频道列表
    
    Args:
        category_id: 分类ID筛选
        search: 搜索关键词
        sort_by: 排序字段
        sort_order: 排序方向
        pagination: 分页参数
        
    Returns:
        List[ChannelSummary]: 频道摘要列表
    """
    try:
        channels = await youtube_service.get_user_channels(
            current_user.id,
            category_id=category_id,
            search=search,
            sort_by=sort_by,
            sort_order=sort_order,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        # 转换为摘要格式
        summaries = []
        for channel in channels:
            summary = ChannelSummary(
                id=channel.id,
                youtube_id=channel.youtube_id,
                title=channel.title,
                thumbnail_url=channel.thumbnail_url,
                subscriber_count=channel.subscriber_count,
                video_count=channel.video_count,
                category_names=channel.category_names if hasattr(channel, 'category_names') else [],
                last_video_published_at=channel.last_video_published_at,
                is_active=channel.is_active,
            )
            summaries.append(summary)
        
        logger.info(f"获取用户频道列表成功", user_id=str(current_user.id), count=len(summaries))
        return summaries
        
    except APIQuotaException as e:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"获取用户频道列表失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取频道列表失败"
        )


@router.get("/{channel_id}", response_model=ChannelInDB, summary="获取频道详细信息")
async def get_channel_detail(
    channel_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    youtube_service: YouTubeService = Depends(get_youtube_service),
) -> ChannelInDB:
    """
    获取指定频道的详细信息
    
    Args:
        channel_id: 频道ID
        
    Returns:
        ChannelInDB: 频道详细信息
    """
    try:
        channel = await youtube_service.get_channel_by_id(channel_id, current_user.id)
        if not channel:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="频道不存在或无访问权限"
            )
        
        logger.info(f"获取频道详情成功", channel_id=str(channel_id), title=channel.title)
        return channel
        
    except HTTPException:
        raise
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"获取频道详情失败: {e}", channel_id=str(channel_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取频道详情失败"
        )


@router.post("/sync", summary="同步用户订阅频道")
async def sync_user_channels(
    sync_request: ChannelSyncRequest,
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_user),
    user_service: UserService = Depends(get_user_service),
) -> Dict[str, Any]:
    """
    同步用户的YouTube订阅频道
    
    Args:
        sync_request: 同步请求参数
        background_tasks: 后台任务
        
    Returns:
        Dict[str, Any]: 同步结果
    """
    try:
        # 检查用户认证状态
        if not current_user.youtube_access_token:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="需要YouTube授权才能同步频道"
            )
        
        # 启动后台同步任务
        background_tasks.add_task(
            user_service.sync_user_subscriptions,
            current_user.id,
            force=sync_request.force,
            categories_only=sync_request.categories_only,
        )
        
        logger.info(f"频道同步任务已启动", user_id=str(current_user.id), force=sync_request.force)
        
        return {
            "message": "频道同步任务已启动",
            "task_id": f"sync_{current_user.id}_{int(time.time())}",
            "estimated_time": "1-5分钟",
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"启动频道同步失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="启动同步任务失败"
        )


@router.put("/{channel_id}", response_model=ChannelInDB, summary="更新频道信息")
async def update_channel(
    channel_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    youtube_service: YouTubeService = Depends(get_youtube_service),
    refresh_data: bool = Query(False, description="是否刷新YouTube数据"),
) -> ChannelInDB:
    """
    更新指定频道的信息
    
    Args:
        channel_id: 频道ID
        refresh_data: 是否从YouTube API刷新数据
        
    Returns:
        ChannelInDB: 更新后的频道信息
    """
    try:
        # 验证频道访问权限
        channel = await youtube_service.get_channel_by_id(channel_id, current_user.id)
        if not channel:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="频道不存在或无访问权限"
            )
        
        if refresh_data:
            # 从YouTube API刷新数据
            updated_channel = await youtube_service.refresh_channel_data(
                channel_id, current_user.id
            )
        else:
            # 仅更新本地缓存时间戳
            updated_channel = await youtube_service.touch_channel(
                channel_id, current_user.id
            )
        
        logger.info(f"频道信息更新成功", channel_id=str(channel_id), refresh=refresh_data)
        return updated_channel
        
    except HTTPException:
        raise
    except APIQuotaException as e:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail=str(e)
        )
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"更新频道信息失败: {e}", channel_id=str(channel_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新频道信息失败"
        )


@router.get("/{channel_id}/videos", summary="获取频道视频列表")
async def get_channel_videos(
    channel_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    youtube_service: YouTubeService = Depends(get_youtube_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    published_after: Optional[str] = Query(None, description="发布时间筛选（ISO格式）"),
    duration_filter: Optional[str] = Query(None, description="时长筛选: short, medium, long"),
) -> Dict[str, Any]:
    """
    获取指定频道的视频列表
    
    Args:
        channel_id: 频道ID
        published_after: 发布时间筛选
        duration_filter: 时长筛选
        pagination: 分页参数
        
    Returns:
        Dict[str, Any]: 视频列表和分页信息
    """
    try:
        # 验证频道访问权限
        channel = await youtube_service.get_channel_by_id(channel_id, current_user.id)
        if not channel:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="频道不存在或无访问权限"
            )
        
        videos, total = await youtube_service.get_channel_videos(
            channel_id,
            current_user.id,
            published_after=published_after,
            duration_filter=duration_filter,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        return {
            "videos": videos,
            "total": total,
            "page": pagination["page"],
            "size": pagination["size"],
            "pages": (total + pagination["size"] - 1) // pagination["size"],
            "channel": {
                "id": str(channel.id),
                "title": channel.title,
                "thumbnail_url": channel.thumbnail_url,
            },
        }
        
    except HTTPException:
        raise
    except APIQuotaException as e:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"获取频道视频失败: {e}", channel_id=str(channel_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取视频列表失败"
        )